﻿#if NETFX_CORE
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
#else
using System.Windows;
using System.Windows.Controls;
#endif

namespace FreshMeat.Xaml
{
   /// <summary>
   /// Control used to wrap the element being dragged by <see cref="DragBehavior"/> and to provide
   /// feedback about the drag operation.
   /// </summary>
   [TemplateVisualState(Name = "Allowed", GroupName = "MoveStates")]
   [TemplateVisualState(Name = "Blocked", GroupName = "MoveStates")]
   [TemplateVisualState(Name = "HasFeedback", GroupName = "FeedbackStates")]
   [TemplateVisualState(Name = "NoFeedback", GroupName = "FeedbackStates")]
   public class DragItem : ContentControl
   {
#if !SILVERLIGHT && !NETFX_CORE
      static DragItem()
      {
         DefaultStyleKeyProperty.OverrideMetadata(typeof(DragItem), new FrameworkPropertyMetadata(typeof(DragItem)));
      }
#endif

      /// <summary>
      /// Dependency property for <see cref="Feedback"/>.
      /// </summary>
      public readonly static DependencyProperty FeedbackProperty = DependencyProperty.Register(
         "Feedback",
         typeof(string),
         typeof(DragItem),
         new PropertyMetadata("", (d, e) => ((DragItem)d).UpdateStates(true)));

      /// <summary>
      /// Dependency property for <see cref="IsAllowed"/>.
      /// </summary>
      public readonly static DependencyProperty IsAllowedProperty = DependencyProperty.Register(
         "IsAllowed",
         typeof(bool),
         typeof(DragItem),
         new PropertyMetadata(true, (d, e) => ((DragItem)d).UpdateStates(true)));

      /// <summary>
      /// Dependency property for <see cref="PopupWidth"/>.
      /// </summary>
      public readonly static DependencyProperty PopupWidthProperty = DependencyProperty.Register(
         "PopupWidth",
         typeof(double),
         typeof(DragItem),
         new PropertyMetadata(50.0));

      /// <summary>
      /// Dependency property for <see cref="PopupHeight"/>.
      /// </summary>
      public readonly static DependencyProperty PopupHeightProperty = DependencyProperty.Register(
         "PopupHeight",
         typeof(double),
         typeof(DragItem),
         new PropertyMetadata(50.0));

      bool ignoreFeedback;

      public DragItem()
      {
         DefaultStyleKey = typeof(DragItem);
      }

#if NETFX_CORE
      protected override void OnApplyTemplate()
#else
      public override void OnApplyTemplate()
#endif
      {
         base.OnApplyTemplate();

         UpdateStates(false);
      }

      //protected override void OnQueryCursor(System.Windows.Input.QueryCursorEventArgs e)
      //{
      //   System.Diagnostics.Trace.TraceInformation("Before: Cursor={0} IsHandled={1}", e.Cursor, e.Handled);


      //   base.OnQueryCursor(e);

      //   System.Diagnostics.Trace.TraceInformation("After: Cursor={0} IsHandled={1}", e.Cursor, e.Handled);
      //}

      void UpdateStates(bool useTransitions)
      {
         var moveState = IsAllowed ? "Allowed" : "Blocked";
         VisualStateManager.GoToState(this, moveState, useTransitions);
         var feedbackState = HasFeedback ? "HasFeedback" : "NoFeedback";
         VisualStateManager.GoToState(this, feedbackState, useTransitions);

         //System.Diagnostics.Trace.TraceInformation("UpdateStates: MoveStates={0} FeedbackStates={1}", moveState, feedbackState);
      }

      public void Update(bool isAllowed, string feedback)
      {
         if (isAllowed)
         {
            // Ignore feedback -- see below for why this is done instead of clearing Feedback.
            ignoreFeedback = true;
            IsAllowed = true;
         }
         else
         {
            IsAllowed = false;

            if (string.IsNullOrWhiteSpace(feedback))
            {
               // The new value is nothing, in which case we set a flag to ignore any existing value
               // rather than clearing the existing value, which allows the UI to fade out (or whatever) 
               // rather than instantly going from text to no text.
               ignoreFeedback = true;
            }
            else
            {
               // The new value is something, in which case it immediately replaces the existing value
               // and we make sure its not being ignored.
               ignoreFeedback = false;
               Feedback = feedback;
            }
         }

         UpdateStates(true);
         //System.Diagnostics.Trace.TraceInformation("isAllowed={0} feedback={1} ignoreFeedback={2}", isAllowed, feedback, ignoreFeedback);
      }

      protected bool HasFeedback
      {
         get { return !string.IsNullOrWhiteSpace(Feedback) && !ignoreFeedback; }
      }

      /// <summary>
      /// Description of why the operation was not allowed.
      /// Ignored when <see cref="IsAllowed"/> is true.
      /// </summary>
      public string Feedback
      {
         get { return (string)GetValue(FeedbackProperty); }
         set { SetValue(FeedbackProperty, value); }
      }

      /// <summary>
      /// Indicates whether the drag operation is allowed.
      /// </summary>
      public bool IsAllowed
      {
         get { return (bool)GetValue(IsAllowedProperty); }
         set { SetValue(IsAllowedProperty, value); }
      }

      /// <summary>
      /// The width of the feedback popup.
      /// </summary>
      public double PopupWidth
      {
         get { return (double)GetValue(PopupWidthProperty); }
         set { SetValue(PopupWidthProperty, value); }
      }

      /// <summary>
      /// The height of the feedback popup.
      /// </summary>
      public double PopupHeight
      {
         get { return (double)GetValue(PopupHeightProperty); }
         set { SetValue(PopupHeightProperty, value); }
      }
   }
}
